package com.itheima.pinda.service.impl;

import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.itheima.pinda.DTO.truck.TruckTypeDto;
import com.itheima.pinda.common.utils.Constant;
import com.itheima.pinda.common.utils.PageResponse;
import com.itheima.pinda.entity.PdTruckTypeGoodsType;
import com.itheima.pinda.entity.truck.PdTruckType;
import com.itheima.pinda.mapper.PdTruckTypeMapper;
import com.itheima.pinda.mapstruct.TruckDTO2Entity;
import com.itheima.pinda.service.PdTruckTypeGoodsTypeService;
import com.itheima.pinda.service.PdTruckTypeService;
import org.apache.commons.lang3.StringUtils;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.math.BigDecimal;
import java.util.List;
import java.util.Objects;
import java.util.stream.Collectors;

@Service
public class PdTruckTypeServiceImpl extends ServiceImpl<PdTruckTypeMapper, PdTruckType> implements PdTruckTypeService {

    @Resource
    private TruckDTO2Entity truckDTO2Entity;


    @Resource
    private PdTruckTypeGoodsTypeService typeGoodsTypeService;

    /**
     * 添加车辆类型
     *
     * @param dto 车辆类型信息
     * @return 车辆类型信息
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public TruckTypeDto saveTruckType(TruckTypeDto dto) {
        PdTruckType pdTruckType = truckDTO2Entity.conver(dto);
        super.save(pdTruckType);
        // entity插入到数据, 其中的id主键, 会被mp自动回填, 这里重新拷贝一下
        dto = truckDTO2Entity.conver(pdTruckType);
        Long pdTruckTypeId = pdTruckType.getId();

        // 处理与货物类型的关联 --> 车辆类型和货物类型中间表
        if (dto.getGoodsTypeIds() != null && dto.getGoodsTypeIds().size() > 0) {
            List<PdTruckTypeGoodsType> pdTruckTypeGoodsTypeList = dto.getGoodsTypeIds()
                    .stream()
                    .map(item -> PdTruckTypeGoodsType.builder()
                            .truckTypeId(String.valueOf(pdTruckTypeId))
                            .goodsTypeId(item)
                            .build())
                    .collect(Collectors.toList());

            typeGoodsTypeService.batchSave(pdTruckTypeGoodsTypeList);
        }

        return dto;
    }

    /**
     * 根据id获取车辆类型详情
     *
     * @param id 车辆类型id
     * @return 车辆类型信息
     */
    @Override
    public TruckTypeDto findById(String id) {
        PdTruckType pdTruckType = super.getOne(Wrappers.<PdTruckType>lambdaQuery()
                .eq(PdTruckType::getId, id)
                .eq(PdTruckType::getStatus, Constant.DATA_DEFAULT_STATUS));

        // 重构为下面的 getGoodsTypeIds方法了, 为了复用
        // List<String> goodTypeIds = typeGoodsTypeService
        //         .findAll(String.valueOf(pdTruckType.getId()), null)
        //         .stream()
        //         .map(PdTruckTypeGoodsType::getGoodsTypeId)
        //         .collect(Collectors.toList());
        List<String> goodTypeIds = this.getGoodsTypeIds(String.valueOf(pdTruckType.getId()));


        TruckTypeDto truckTypeDto = truckDTO2Entity.conver(pdTruckType);
        truckTypeDto.setGoodsTypeIds(goodTypeIds);
        return truckTypeDto;
    }

    /**
     * 获取车辆类型分页数据
     *
     * @param page            页码
     * @param pageSize        页尺寸
     * @param name            车辆类型名称
     * @param allowableLoad   车辆载重
     * @param allowableVolume 车辆体积
     * @return 车辆类型分页数据
     */
    @Override
    public PageResponse<TruckTypeDto> findByPage(Integer page, Integer pageSize,
                                                 String name, BigDecimal allowableLoad, BigDecimal allowableVolume) {
        Page<PdTruckType> pdTruckTypePage = super.page(new Page<>(page, pageSize), Wrappers.<PdTruckType>lambdaQuery()
                .like(StringUtils.isNotBlank(name), PdTruckType::getName, name)
                .eq(Objects.nonNull(allowableLoad), PdTruckType::getAllowableLoad, allowableLoad)
                .eq(Objects.nonNull(allowableVolume), PdTruckType::getAllowableVolume, allowableVolume)
                .eq(PdTruckType::getStatus, Constant.DATA_DEFAULT_STATUS));

        return PageResponse.<TruckTypeDto>builder()
                .page(page)
                .pagesize(pageSize)
                .pages(pdTruckTypePage.getPages())
                .counts(pdTruckTypePage.getTotal())
                .items(pdTruckTypePage.getRecords()
                        .stream()
                        .map(item -> {
                            TruckTypeDto truckTypeDto = truckDTO2Entity.conver(item);
                            List<String> goodTypeIds = this.getGoodsTypeIds(String.valueOf(item.getId()));
                            truckTypeDto.setGoodsTypeIds(goodTypeIds);
                            return truckTypeDto;
                        })
                        .collect(Collectors.toList()))
                .build();
    }

    /**
     * 获取车辆类型列表
     *
     * @param ids 车辆类型id
     * @return 车辆类型列表
     */
    @Override
    public List<TruckTypeDto> findAll(List<String> ids) {
        List<TruckTypeDto> collect;

        collect = super.list(Wrappers.<PdTruckType>lambdaQuery()
                .in(ids != null && ids.size() > 0, PdTruckType::getId, ids)
                .eq(PdTruckType::getStatus, Constant.DATA_DEFAULT_STATUS))
                .stream()
                .map(item -> {
                    TruckTypeDto truckTypeDto = truckDTO2Entity.conver(item);
                    List<String> goodTypeIds = this.getGoodsTypeIds(String.valueOf(item.getId()));
                    truckTypeDto.setGoodsTypeIds(goodTypeIds);
                    return truckTypeDto;
                }).collect(Collectors.toList());
        return collect;
    }


    /**
     * 根据车辆类型Id, 从车辆类型和货物类型中间表获取 货物类型Id集合
     *
     * @param pdTruckTypeId 车辆类型Id
     * @return List<String>
     */
    private List<String> getGoodsTypeIds(String pdTruckTypeId) {
        return typeGoodsTypeService
                .findAll(String.valueOf(pdTruckTypeId), null)
                .stream()
                .map(PdTruckTypeGoodsType::getGoodsTypeId)
                .collect(Collectors.toList());
    }

    /**
     * 更新车辆类型信息
     *
     * @param id  车辆类型id
     * @param dto 车辆类型信息
     * @return 车辆类型信息
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public TruckTypeDto updateTruckType(String id, TruckTypeDto dto) {
        dto.setId(id);
        PdTruckType pdTruckType = truckDTO2Entity.conver(dto);
        String pdTruckTypeId = String.valueOf(pdTruckType.getId());
        super.updateById(pdTruckType);
        dto = truckDTO2Entity.conver(pdTruckType);

        // 重新更新中间表的关联信息
        if (dto.getGoodsTypeIds() != null && dto.getGoodsTypeIds().size() > 0) {
            // 删除原先的与货物类型的关联
            typeGoodsTypeService.delete(pdTruckTypeId, null);
            // 绑定新的关系
            typeGoodsTypeService.batchSave(dto.getGoodsTypeIds()
                    .stream()
                    .map(goodTypeId -> PdTruckTypeGoodsType.builder()
                            .truckTypeId(id)
                            .goodsTypeId(goodTypeId)
                            .build())
                    .collect(Collectors.toList()));
        }

        return dto;
    }
}
